package com.pig4cloud.pigx.contract.executer.position.multiple_changer.impl;

import com.alibaba.nacos.common.utils.Objects;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.customize.i18n.util.MessageUtils;
import com.pig4cloud.pigx.common.customize.mysql.utils.MysqlUtil;
import com.pig4cloud.pigx.common.customize.utils.CommonUtil;
import com.pig4cloud.pigx.common.seata.utils.SeataUtils;
import com.pig4cloud.pigx.contract.bo.ContractPositionMultipleChangeBO;
import com.pig4cloud.pigx.contract.constant.I18nMessages;
import com.pig4cloud.pigx.contract.entity.ContractPosition;
import com.pig4cloud.pigx.contract.enums.ContractPositionEnum;
import com.pig4cloud.pigx.contract.executer.position.multiple_changer.PositionMultipleChangerManager;
import com.pig4cloud.pigx.contract.executer.position.supporter.PositionCalculator;
import com.pig4cloud.pigx.contract.mapper.ContractPositionMapper;
import com.pig4cloud.pigx.contract.utils.ContractUtils;
import com.pig4cloud.pigx.wallet.dto.WalletContractAccountChangeDTO;
import com.pig4cloud.pigx.wallet.enums.WalletContractAccountDetailEnum;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;

/**
 * 全仓仓位杠杆调整器
 *
 * @since 2022/8/17 21:26
 */
@Component
public class FullPositionMultipleChanger extends AbstractPositionMultipleChanger
        implements InitializingBean {

    protected final PositionMultipleChangerManager positionMultipleChangerManager;

    /**
     * 全参构造函数
     *
     * @since 2022/9/8 14:45
     */
    public FullPositionMultipleChanger(ContractUtils contractUtils,
                                       CommonUtil commonUtil,
                                       MysqlUtil mysqlUtil,
                                       ContractPositionMapper contractPositionMapper,
                                       PositionMultipleChangerManager positionMultipleChangerManager) {
        super(contractUtils, commonUtil, mysqlUtil, contractPositionMapper);
        this.positionMultipleChangerManager = positionMultipleChangerManager;
    }

    /**
     * 当对象创建后
     *
     * @since 2022/9/8 11:07
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        positionMultipleChangerManager.getMultipleHandlerList().add(this);
    }

    /**
     * 判断是否支持
     *
     * @param bo bo
     * @return {@link boolean}
     * @since 2022/8/17 11:20
     */
    @Override
    public boolean support(ContractPositionMultipleChangeBO bo) {
        // 同一币对下仓位模式相同
        ContractPosition position = bo.getFirstPosition();
        return Objects.equals(ContractPositionEnum.Mode.FULL.getValue(), position.getMode());
    }

    /**
     * 处理因杠杆倍数变化导致更改的其它相关数据
     *
     * @param bo bo
     * @since 2022/9/8 12:04
     */
    @Override
    protected void handleRelevantData(ContractPositionMultipleChangeBO bo) {
        ContractPosition position = bo.getFirstPosition();

        List<ContractPosition> list = bo.getList();
        // 统计仓位的总共差额
        BigDecimal totalDifference = BigDecimal.ZERO;
        for (ContractPosition i : list) {
            // 计算标准保证金 - 当前全仓持仓保证金的差额
            BigDecimal difference = PositionCalculator.getFullStandardMarginDifference(i.getOpenAvgPrice(),
                    i.getNowNum(),
                    i.getMultiple(),
                    i.getMargin());

            // 修改JVM持仓保证金
            i.setMargin(i.getMargin().add(difference));
            // 累计总差异金额
            totalDifference = totalDifference.add(difference);
        }

        int compare = totalDifference.compareTo(BigDecimal.ZERO);
        if (compare != 0) {
            // 开启全局事务
            SeataUtils.startGlobalTx();

            // 多退少补
            WalletContractAccountChangeDTO marginParam = ContractUtils.getChangeAssetParamByPosition(position,
                    totalDifference.abs(),
                    null,
                    WalletContractAccountDetailEnum.BusinessType.POSITION_MARGIN,
                    compare > 0 ? WalletContractAccountDetailEnum.OperationType.ADD : WalletContractAccountDetailEnum.OperationType.MINUS,
                    false);
            R<?> r = contractUtils.changeAsset(Collections.singletonList(marginParam));
            if (!r.getIsSuccess()) {
                throw new RuntimeException(MessageUtils.get(I18nMessages.OPERATION_FAILURE));
            }

            // 记录合约账户变更操作
            bo.setHasChangeAsset(true);
        }
    }

    /**
     * 杠杆调整成功
     *
     * @param bo bo
     * @since 2022/8/17 11:31
     */
    @Override
    public void success(ContractPositionMultipleChangeBO bo) {
        // 提交全局事务
        SeataUtils.commitGlobalTx();

        super.success(bo);

        // 如果修改过合约账户，发送重算强平价消息
        if (bo.getHasChangeAsset()) {
            contractUtils.sendPositionCrossCalculate(bo.getDto().getUserId());
        }
    }
}
